home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 July / EnigmA AMIGA RUN 20 (1997)(G.R. Edizioni)(IT)[!][issue 1997-07 & 08][EAR-CD IV].iso / earcd / dev / c / amcsrc2.lha / AMCSources2 / NeuralN / NNTRAIN.c < prev    next >
C/C++ Source or Header  |  1996-06-06  |  9KB  |  429 lines

  1. /*
  2. *-----------------------------------------------------------------------------
  3. *    file:    nntrain.c
  4. *    desc:    train a fully connected neural net by backpropagation
  5. *    by:    patrick ko
  6. *    date:    2 aug 91
  7. *    revi:    v1.2b - 15 jan 92, adaptive coefficients
  8. *        v1.3u - 18 jan 92, revised data structures
  9. *        v1.31u - 20 jan 92, periodic dump, weights retrieval
  10. *-----------------------------------------------------------------------------
  11. */
  12. #include <stdio.h>
  13. #include <math.h>
  14. #ifdef AMIGA
  15. #include <float.h>
  16. #define MAXFLOAT FLT_MAX
  17. #else
  18. #include <values.h>
  19. #endif
  20. #include <time.h>
  21.  
  22. #include "nntype.h"
  23. #include "nnmath.h"
  24. #include "nntrain.h"
  25. #include "nndump.h"
  26.  
  27. #define    global
  28. #define    LAMBDA0    0.1
  29.  
  30. static REAL    ETA = ETA_DEFAULT;
  31. static REAL    MOMENTUM = ALPHA_DEFAULT;
  32. static REAL    LAMBDA = LAMBDA_DEFAULT;
  33. static INTEGER    REPINTERVAL = 0;
  34. global REAL    TOLER = TOLER_DEFAULT;
  35.  
  36. /*
  37. *=============================================================================
  38. *    funct:    nnbp_train
  39. *    dscpt:    train a neural net using backpropagation
  40. *    given:    net = the neural net
  41. *        inpvect = 1 input vector ( 1 train pattern )
  42. *        tarvect = 1 target vector ( 1 target pattern )
  43. *        np = number of patterns
  44. *        err = error
  45. *        eta, momentum
  46. *        report = dump info interval (no.of train cycles), 0=not dump
  47. *        tdump = no of seconds for periodic dump, 0=not dump
  48. *        dfilename = period dump file name
  49. *    retrn:    measure of error
  50. *=============================================================================
  51. */
  52. REAL nnbp_train( net, inpvect, tarvect, np, err, eta, momentum, report, tdump, dfilename )
  53. NET    *net;
  54. VECTOR    **inpvect;
  55. VECTOR    **tarvect;
  56. REAL    err, eta, momentum;
  57. INTEGER    np, report;
  58. long int tdump;
  59. char    *dfilename;
  60. {
  61.     REAL    Error;
  62.     INTEGER    cnt;
  63.     time_t    lasttime, thistime;
  64.     FILE    *fdump;
  65.  
  66.  
  67.     cnt = 0;
  68.     REPINTERVAL = report;
  69.     ETA = eta;
  70.     MOMENTUM = momentum;
  71.     Error = MAXFLOAT;
  72.     if (tdump)
  73.         time(&lasttime);
  74.  
  75.     while (Error > err)
  76.         {
  77.         cnt++;
  78.         Error = nnbp_train1( net, inpvect, tarvect, np, Error );
  79.  
  80.         if (report)
  81.             nnbp_report(cnt, Error);
  82.         if (tdump)
  83.             {
  84.             if (((thistime = time(&thistime)) - lasttime) >= tdump)
  85.                 {
  86.                 fdump = fopen( dfilename, "w" );
  87.                 nn_dump( fdump, net );
  88.                 fclose(fdump);
  89.                 lasttime = thistime;
  90.                 }
  91.             }
  92.         }
  93.     return (Error);
  94. }
  95.  
  96. /*
  97. *=============================================================================
  98. *    funct:    nnbp_report
  99. *    dscpt:    print report lines to terminal
  100. *    given:    cnt = number of train cycles
  101. *        error = overall energy
  102. *    retrn:    nothing
  103. *=============================================================================
  104. */
  105. void nnbp_report( cnt, error )
  106. INTEGER    cnt;
  107. REAL    error;
  108. {
  109.     if (!(cnt%REPINTERVAL))
  110.         {
  111.         printf("nntrain: cycle= %d, MSE/Unit =%f\n", cnt, error );
  112.         fflush(stdout);
  113.         }
  114. }
  115.  
  116. /*
  117. *=============================================================================
  118. *    funct:    nnbp_train1
  119. *    dscpt:    train a neural net 1 cycle using backpropagation
  120. *    given:    net = the neural net
  121. *        inpvect = 1 set of input vectors
  122. *        tarvect = 1 set of target vectors
  123. *        np = number of patterns
  124. *        LastError = energy at last cycle
  125. *    retrn:    measure of error after this train cycle
  126. *=============================================================================
  127. */
  128. REAL nnbp_train1( net, inpvect, tarvect, np, LastError )
  129. NET    *net;
  130. VECTOR    **inpvect;
  131. VECTOR     **tarvect;
  132. INTEGER    np;
  133. REAL    LastError;
  134. {
  135.     REAL    Error;
  136.     INTEGER    i;
  137.     INTEGER    fire=0;
  138.  
  139.     Error = 0.0;
  140.     nnbp_init( net );
  141.     for (i=0; i<np; i++)
  142.         {
  143.         nnbp_forward( net, *(inpvect + i));
  144.         Error += nnbp_backward( net, *(inpvect + i), *(tarvect + i));
  145.         }
  146.     Error = Error / np / DimNetOut(net);
  147.     /*
  148.     * coefficients adaptation and dWeight calculations
  149.     */
  150.     if (Error <= LastError + TOLER )
  151.         {
  152.  
  153.         /* weights will be updated, go ahead */
  154.  
  155.         fire = 1;
  156.         nnbp_coeffadapt( net );
  157.         nnbp_dweightcalc( net, np, fire );
  158.         return (Error);
  159.         }
  160.     else
  161.         {
  162.  
  163.         /* weights will not be updated, backtrack */
  164.  
  165.         fire = 0;
  166.         ETA *= BACKTRACK_STEP;        /* half the ETA */
  167.         ETA = ground(ETA,ETA_FLOOR);
  168.         MOMENTUM = ETA * LAMBDA;
  169.         nnbp_dweightcalc( net, np, fire );
  170.         return (LastError);
  171.         }
  172. }
  173.  
  174. /*
  175. *=============================================================================
  176. *    funct:    nnbp_forward (pass)
  177. *    dscpt:    forward pass calculation
  178. *    given:    net = the neural net
  179. *        inpvect = 1 input vector ( 1 train pattern )
  180. *    retrn:    nothing
  181. *    cmmnt:    net's output Out(J) calculated at every unit
  182. *=============================================================================
  183. */
  184. void nnbp_forward( net, inpvect )
  185. NET    *net;
  186. VECTOR    *inpvect;
  187. {
  188.     LAYER    *I, *input;
  189.     UNIT    *J;
  190.     INTEGER    i, j, k;
  191. //    REAL    sum;
  192.         REAL    out;
  193.  
  194.     /* phase 1 - forward compute output value Out's */
  195.  
  196.     input = NULL;
  197.  
  198.     /* For each layer I in the network */
  199.  
  200.     for (i=0; i<DimNet(net); i++)
  201.         {
  202.         I = Layer(net,i);
  203.  
  204.         /* For each unit J in the layer */
  205.  
  206.         for (j=0; j<DimLayer(I); j++)
  207.             {
  208.             J = Unit(I,j);
  209.             Net(J) = Bias(J) + dBias1(J); /* add bias */
  210.             for (k=0; k<DimvWeight(J); k++)
  211.                 {
  212.                 if (i==0)
  213.                     out = Vi(inpvect,k);
  214.                 else
  215.                     out = Out(Unit(input,k));
  216.  
  217.                 Net(J) += (Weight(J,k) + dWeight1(J,k)) * out;
  218.                 }
  219.             Out(J) = sigmoid(Net(J));
  220.             }
  221.         input = I;
  222.         }
  223. }
  224.  
  225.  
  226. void nnbp_init( net )
  227. NET    *net;
  228. {
  229.     LAYER    *I;
  230.     UNIT    *J;
  231.     INTEGER    i, j, k;
  232.  
  233.     i = DimNet(net);
  234.  
  235.     while (i--)
  236.         {
  237.         I = Layer(net,i);
  238.         for (j=0; j<DimLayer(I); j++)
  239.             {
  240.             J = Unit(I,j);
  241.             nDlt(J) = 0.0;
  242.             for (k=0; k<DimvWeight(J); k++)
  243.                 {
  244.                 DO(J,k) = 0.0;
  245.                 }
  246.             }
  247.         }
  248. }
  249.  
  250. /*
  251. *=============================================================================
  252. *    funct:    nnbp_backward
  253. *    dscpt:    backward pass calculation
  254. *    given:    net = the neural net
  255. *        inpvect = 1 input vector ( 1 train pattern )
  256. *        tarvect = 1 target vector
  257. *    retrn:    Ep * 2
  258. *    cmmnt:    net's weight and bias adjusted at every layer
  259. *=============================================================================
  260. */
  261. REAL nnbp_backward( net, inpvect, tarvect )
  262. NET    *net;
  263. VECTOR    *inpvect;
  264. VECTOR    *tarvect;
  265. {
  266.     LAYER    *I, *F, *B;
  267.     UNIT    *J, *JF;
  268.     INTEGER    i, j, k;
  269.     REAL    sum, out;
  270.     REAL    Ep, diff;
  271.  
  272.     Ep = 0.0;
  273.  
  274.     /*
  275.     *    phase 2 - target comparison and back propagation
  276.     */
  277.     i = DimNet(net) - 1;
  278.     F = I = Layer(net,i);
  279.     B = Layer(net,i - 1);
  280.  
  281.     /*
  282.     *    Delta rule 1 - OUTPUT LAYER
  283.     *    dpj = (tpj - opj) * f'(netpj)
  284.     */
  285.     for (j=0; j<DimLayer(I); j++)
  286.         {
  287.         J = Unit(I,j);
  288.         diff = Vi(tarvect,j) - Out(J);
  289.         Dlt(J) = diff * Out(J) * (1.0 - Out(J));
  290.  
  291.         nDlt(J) += Dlt(J);    /* accumulate Dpj's */
  292.  
  293.         for (k=0; k<DimvWeight(J); k++)
  294.             {
  295.             if (i==0)
  296.                 out = Vi(inpvect,k);
  297.             else
  298.                 out = Out(Unit(B,k));
  299.             DO(J,k) += Dlt(J) * out;
  300.             }
  301.  
  302.         Ep += diff * diff;
  303.         }
  304.  
  305.     --i;
  306.     while (i >= 0)
  307.         {
  308.         I = Layer(net,i);        /* current layer */
  309.         B = Layer(net,i - 1);
  310.         /*
  311.         *    delta rule 2 - HIDDEN LAYER:
  312.         *    dpj = f'(netpj) * SUMMATEk( Dpk * Wkj )
  313.         */
  314.         for (j=0; j<DimLayer(I); j++)
  315.             {
  316.             J = Unit(I,j);
  317.             sum = 0.0;
  318.             for (k=0; k<DimLayer(F); k++)
  319.                 {
  320.                 JF = Unit(F,k);
  321.                 sum += Dlt(JF) * (Weight(JF,j)+dWeight1(JF,j));
  322.                 }
  323.             Dlt(J) = Out(J) * (1.0 - Out(J)) * sum;
  324.             nDlt(J) += Dlt(J);
  325.  
  326.             for (k=0; k<DimvWeight(J); k++)
  327.                 {
  328.                 if (i==0)
  329.                     out = Vi(inpvect,k);
  330.                 else
  331.                     out = Out(Unit(B,k));
  332.                 DO(J,k) += Dlt(J) * out;
  333.                 }
  334.             }
  335.         F = I;
  336.         i--;
  337.         }
  338.  
  339.     return (Ep);
  340. }
  341.  
  342. void nnbp_coeffadapt( net )
  343. NET    *net;
  344. {
  345.     LAYER    *I;
  346. //        LAYER   *B;
  347.     UNIT    *J;
  348. //    INTEGER    n;
  349.         INTEGER i, j, k;
  350.     REAL    EW, ME, MW, costh;
  351.  
  352.     EW = ME = MW = 0.0;
  353.     i = DimNet(net);
  354.  
  355.     while (i--)
  356.         {
  357.         I = Layer(net,i);
  358.         for (j=0; j<DimLayer(I); j++)
  359.             {
  360.             J = Unit(I,j);
  361.             for (k=0; k<DimvWeight(J); k++)
  362.                 {
  363.                 ME += DO(J,k) * DO(J,k);
  364.                 MW += dWeight1(J,k) * dWeight1(J,k);
  365.                 EW += DO(J,k) * dWeight1(J,k);
  366.                 }
  367.             }
  368.         }
  369.  
  370.     ME = sqrt(ME);        /* modulus of cost funct vector E */
  371.     MW = sqrt(MW);        /* modulus of delta weight vector dWn-1*/
  372.  
  373.     ME = ground(ME,ME_FLOOR);        /* constraints */
  374.     MW = ground(MW,MW_FLOOR);        /* constraints */
  375.  
  376.     costh = EW / (ME * MW);
  377.  
  378.     /* coefficients adaptation !!! */
  379.  
  380.     ETA = ETA * (1.0 + 0.5 * costh);
  381.     ETA = ground(ETA,ETA_FLOOR);
  382.     LAMBDA = LAMBDA0 * ME / MW;
  383.     MOMENTUM = ETA * LAMBDA;
  384. }
  385.  
  386. void nnbp_dweightcalc( net, np, fire )
  387. NET    *net;
  388. INTEGER    np;
  389. INTEGER    fire;
  390. {
  391.     LAYER    *I;
  392.     UNIT    *J;
  393. //    INTEGER    n;
  394.         INTEGER i, j, k;
  395.  
  396.     i = DimNet(net);
  397.  
  398.     /* calculate dWeights for every unit */
  399.  
  400.     while (i--)
  401.         {
  402.         I = Layer(net,i);
  403.         for (j=0; j<DimLayer(I); j++)
  404.             {
  405.             J = Unit(I,j);
  406.             nDlt(J) /= np;
  407.             for (k=0; k<DimvWeight(J); k++)
  408.                 {
  409.                 DO(J,k) /= np;
  410.                 if (fire)
  411.                     {
  412.                     /* commit weight change */
  413.                     Weight(J,k) += dWeight1(J,k);
  414.  
  415.                     /* dW n-2 = dW n-1 */
  416.                     dWeight2(J,k) = dWeight1(J,k);
  417.                     }
  418.                 dWeight1(J,k) = ETA * DO(J,k) + MOMENTUM * dWeight2(J,k);
  419.                 }
  420.             if (fire)
  421.                 {
  422.                 Bias(J) += dBias1(J);
  423.                 dBias2(J) = dBias1(J);
  424.                 }
  425.             dBias1(J) = ETA * nDlt(J) + MOMENTUM * dBias2(J);
  426.             }
  427.         }
  428. }
  429.